﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainTechLLC.EmlenMud.Communication;
using BrainTechLLC;
using BrainTechLLC.ThreadSafeObjects;
using System.Net;
using System.Threading;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using BrainTechLLC.ImageOperatorsNonAForgeDependent;
using BrainTechLLC.WebCamLib3;

namespace WpfImageBroadcaster
{
    public class Communications
    {
        const int PortNum = 4006;
        CommunicationsServer _server;
        ServerMessageHandler _messageHandler;
        public ThreadSafeQueue<Bitmap> OutgoingBitmapQueue = new ThreadSafeQueue<Bitmap>();
        ImageCodecInfo codec;
        EncoderParameters parameters;

        public Communications()
        {
            JpegEncoding.GetJPEGParamsForConversionQuality(90, out codec, out parameters);
        }

        public void Startup()
        {
            if (_server == null)
            {
                // Set up the server that will accept incoming connections
                _messageHandler = new ServerMessageHandler();
                _server = new CommunicationsServer(IPAddress.Any, PortNum, _messageHandler);
                _server.BeginListening();

                ThreadStart ts = new ThreadStart(BroadcastThreadWorker);
                ts.CreateAndRunThread(true);
            }
        }

        public void BroadcastThreadWorker()
        {
            while (true)
            {
                Bitmap item;

                if (OutgoingBitmapQueue.Dequeue(out item))
                {
                    Broadcast(item);
                }
                else
                {
                    Thread.Sleep(20);
                }

                if (OutgoingBitmapQueue.Count > 10)
                {
                    OutgoingBitmapQueue.Clear();
                }
            }
        }

        public void Broadcast(Bitmap bm)
        {
            var allConnections = _server.Connections.AllItems;
            int packetSize = 0;
            byte[] imageBytes = ImageToBytes(bm, codec, parameters, ref packetSize);
            // ICommunicationsMessage message = new Message(imageBytes, 0, new MessageHeader(packetSize, 0));

            for (int n = 0; n < allConnections.Count; n++)
            {
                try
                {
                    allConnections[n].SendMessage(imageBytes, 0);
                }
                catch { }
            }
        }

        public Bitmap ExtractImageFromBytes(byte[] rgBytes)
        {
            Bitmap img = null;
            MemoryStream ms = new MemoryStream(rgBytes);
            ms.Seek(0, SeekOrigin.Begin);
            try { img = (Bitmap)Image.FromStream(ms); }
            catch { }
            return img;
        }

        public static byte[] ImageToBytes(Image img, ImageCodecInfo codecinfo, EncoderParameters encoderParams, ref int nPacketSize)
        {
            if (img == null) return null;

            int nLen;
            byte[] rgBytes;

            using (MemoryStream ms = new MemoryStream(64000))
            {
                ms.Seek(0, SeekOrigin.Begin);
                // serialize the image using the specified codec and encoding parameters
                img.Save(ms, codecinfo, encoderParams);
                ms.Seek(0, SeekOrigin.Begin);
                // Calculate the length of the image plus its header
                nLen = (int)(ms.Length);
                // Copy the memory stream into a fixed-size byte buffer
                rgBytes = new byte[nLen];
                ms.Seek(0, SeekOrigin.Begin);
                Array.Copy(ms.GetBuffer(), rgBytes, nLen);
                ms.Close();
            }
            // return the packet size to the caller in a ref parameter
            nPacketSize = nLen;
            return rgBytes;
        }
    }
}
